using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using ImageLib.Data.Database;
using ImageLib.Data.Extension;
using ImageLib.Shell.Model;
using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.IO;
using System.Diagnostics;

namespace ImageLib.Shell.ViewModel
{
    /// <summary>
    /// This class contains properties that the main View can data bind to.
    /// <para>
    /// Use the <strong>mvvminpc</strong> snippet to add bindable properties to this ViewModel.
    /// </para>
    /// <para>
    /// You can also use Blend to data bind with the tool's support.
    /// </para>
    /// <para>
    /// See http://www.galasoft.ch/mvvm
    /// </para>
    /// </summary>
    public class MainViewModel : ViewModelBase, IInitable
    {
        
        private MainModel _model;

        #region Ctors
        /// <summary>
        /// Initializes a new instance of the MainViewModel class.
        /// </summary>
        public MainViewModel()
        {
            _model = new MainModel();
            Libraries = new ObservableCollection<CommandItem<Library>>();
            Images = new ObservableCollection<ImageItem>();
            Folders = new ObservableCollection<string>();

            if (IsInDesignMode)
            {
                // Code runs in Blend --> create design time data.
            }
            else
            {
                // Code runs "for real"
            }
            
            // Commands
            MainCommand = new RelayCommand<string>(ExecuteMainCommand, CanExecuteMainCommand);
                     
        }
        #endregion

        #region IInitable Members

        public void Initialize()
        {
            LoadLibraries();
            ImageListType = MainModel.CommandKey.ShowSmallIcons;
        }

        #endregion

        #region MainCommand

        public RelayCommand<string> MainCommand { get; set; }

        private bool CanExecuteMainCommand(string commandKey)
        {
            return true;
        }

        private void ExecuteMainCommand(string commandKey)
        {
            switch (commandKey)
            {
                case MainModel.CommandKey.AddLibrary:
                    var libraryId = _model.AddLibrary(MainModel.SelectDirectory());
                    LoadLibraries();
                    LoadLibrary(libraryId);                    
                    break;
                case MainModel.CommandKey.GetCurrentLibraryImages:
                    LoadCurrentLibraryImages();
                    break;
                case MainModel.CommandKey.GetCurrentFolderImages:
                    LoadCurrentFolderImages();
                    break;

                case MainModel.CommandKey.ShowSmallIcons:
                case MainModel.CommandKey.ShowLargeIcons:
                case MainModel.CommandKey.ShowTiles:
                case MainModel.CommandKey.ShowContent:
                    ImageListType = commandKey;
                    break;
                default:
                    break;
            }
        }
        #endregion

        private void LoadLibrary(Library lib)
        {
            if (lib == null) { return; }
            LoadLibrary(lib.Id);
        }

        private void LoadLibrary(Guid libraryId)
        {
            if (libraryId == Guid.Empty) { return; }
            ChangeCurrentLibrary(libraryId);
            LoadCurrentLibraryImages();
        }

        public string CurrentLibraryName
        {
            get { return _model.CurrentLibrary == null ? null : _model.CurrentLibrary.Name; }
            set
            {
                if (_model.CurrentLibrary == null || _model.CurrentLibrary.Name == value) { return; }
                
                _model.CurrentLibrary.Name = value;
                RaisePropertyChanged("CurrentLibraryName");
            }
        }

        public string CurrentLibraryPath
        {
            get { return _model.CurrentLibrary == null ? null : _model.CurrentLibrary.Path; }
            set
            {
                if (_model.CurrentLibrary == null || _model.CurrentLibrary.Path == value) { return; }

                _model.CurrentLibrary.Path = value;
                RaisePropertyChanged("CurrentLibraryPath");
            }
        }
                
        public string CurrentFolder
        {
            get { return _model.CurrentFolder; }
            set
            {
                if (_model.CurrentFolder == value) { return; }
                _model.CurrentFolder = value;
                RaisePropertyChanged("CurrentFolder");
                LoadCurrentFolderImages();
            }
        }

        public ObservableCollection<CommandItem<Library>> Libraries { get; private set; }

        public ObservableCollection<string> Folders { get; private set; }

        public ObservableCollection<ImageItem> Images { get; private set; }
                
        public string ImageListType
        {
            get { return _model.ImageListType; }
            set
            {
                if (_model.ImageListType == value) { return; }
                
                _model.ImageListType = value;
                RaisePropertyChanged("ImageListType");
            }
        }

        private void LoadImage(Image image)
        {
            if (image == null) { return; }

            string currentDirPath = GetCurrentDirPath(image.Path);

            if (currentDirPath == null) { return; }

            string fullPath = image.GetFullPath(currentDirPath);
            Process.Start("explorer.exe", fullPath);
        }

        public bool ShowAllImages
        {
            get { return _model.ShowAllImages; }
            set
            {
                if (_model.ShowAllImages == value) { return; }
                _model.ShowAllImages = value;
                RaisePropertyChanged("ShowAllImages");
            }
        }
        

        private void ChangeCurrentLibrary(Guid libraryId)
        {
            _model.SetCurrentLibrary(libraryId);

            LoadFolders();

            RaisePropertyChanged("CurrentLibraryName");
            RaisePropertyChanged("CurrentLibraryPath");
        }

        private void LoadLibraries()
        {
            Libraries.Clear();
            foreach (var lib in _model.GetLibraries())
            {
                Libraries.Add(new CommandItem<Library>(lib, LoadLibrary));
            }
        }

        private void LoadFolders()
        {
            Folders.Clear();
            foreach (var fldr in _model.Folders)
            {
                Folders.Add(fldr);
            }
        }

        private void LoadCurrentLibraryImages()
        {
            ShowAllImages = true;
            Images.Clear();
            var images = _model.GetCurrentLibraryImages().OrderBy((img) => img.Name);

            AddImages(images);
        }

        private void LoadCurrentFolderImages()
        {
            ShowAllImages = false;
            Images.Clear();
            var images = _model.GetCurrentFolderImages().OrderBy((img) => img.Name);

            AddImages(images);
        }

        private void AddImages(IOrderedEnumerable<Image> images)
        {
            foreach (var img in images)
            {
                
                

                Images.Add(new ImageItem(img, LoadImage));
            }
        }

        private string GetCurrentDirPath(string folderPath)
        {
            string libraryPath = CurrentLibraryPath;
            return MainModel.GetDirPath(libraryPath, folderPath);
        }

                        
    }
}